using System;
using System.Collections;
using System.IO;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace stsdev {
  
  public class SolutionConfigBuilder {

    #region "Create method overloads with optional parameter support"
    public static void Create(string FilePath) {
      Create(FilePath, true);
    }

    public static void Create(string FilePath, bool AssemblyDeployment) {
      Create(FilePath, 
             AssemblyDeployment,
             false);
    }

    public static void Create(string FilePath, bool AssemblyDeployment, bool SafeControlSettings) {
      Create(FilePath, 
             AssemblyDeployment, 
             SafeControlSettings,
             AssemblyDeploymentTarget.GlobalAssemblyCache);
    }

    public static void Create(string FilePath, bool AssemblyDeployment, bool SafeControlSettings, AssemblyDeploymentTarget DeploymentTarget) {
      Create(FilePath,
            AssemblyDeployment,
            SafeControlSettings,
            AssemblyDeploymentTarget.GlobalAssemblyCache,
            null);
    }
    #endregion

    public static void Create(string FilePath, bool AssemblyDeployment, bool SafeControlSettings, AssemblyDeploymentTarget DeploymentTarget, PermissionSet CasPermissions) {

      StreamWriter manifestStream = new StreamWriter(FilePath);
      XmlWriterSettings settings = new XmlWriterSettings();
      settings.Encoding = Encoding.UTF8;
      settings.Indent = true;
      settings.NewLineOnAttributes = false;
      settings.NewLineHandling = NewLineHandling.None;
      XmlWriter writer = XmlWriter.Create(manifestStream, settings);
      writer.WriteStartDocument();

      writer.WriteComment("Created by STSDEV at " + DateTime.Now.ToString());
      writer.WriteStartElement("Solution");

      // create new guid and use it as solution ID
      writer.WriteStartElement("SolutionId");
      SolutionBuilder.SolutionId = Guid.NewGuid().ToString().ToUpper();
      writer.WriteValue(SolutionBuilder.SolutionId);
      writer.WriteEndElement();

      // add solution name
      writer.WriteStartElement("SolutionName");
      writer.WriteValue(SolutionBuilder.SolutionName);
      writer.WriteEndElement();

      // add 'feature.xml' reference
      writer.WriteStartElement("Features");
      writer.WriteStartElement("Feature");
      writer.WriteAttributeString("Primary", "True");
      writer.WriteValue(@"feature.xml");
      writer.WriteEndElement();
      writer.WriteEndElement(); 

      // add value to track whether solution deployment/upgrade issues IISRESET
      writer.WriteStartElement("ResetWebServer");
      writer.WriteValue("True");
      writer.WriteEndElement();

      // add boolean to track whether solution needs assembly in deployment package
      writer.WriteStartElement("AssemblyDeployment");
      writer.WriteValue(AssemblyDeployment.ToString());
      writer.WriteEndElement();

      // add boolean to track whether solution needs assembly in deployment package
      writer.WriteStartElement("SafeControlSettings");
      writer.WriteValue(SafeControlSettings.ToString());
      writer.WriteEndElement();

      // add boolean to track whether solution needs assembly in deployment package
      writer.WriteStartElement("CasPermissions");
      writer.WriteValue((CasPermissions != null).ToString());
      writer.WriteEndElement();

      if (AssemblyDeployment) {
        // write Assembly Files
        writer.WriteComment("Assembly files");
        writer.WriteStartElement("Assemblies");
        writer.WriteStartElement("Assembly");
        writer.WriteAttributeString("Location", SolutionBuilder.TargetName + ".dll");
        writer.WriteAttributeString("DeploymentTarget", DeploymentTarget.ToString());
        writer.WriteStartElement("SafeControls");
        writer.WriteStartElement("SafeControl");
        writer.WriteAttributeString("Assembly", SolutionBuilder.FullAssemblyName);
        writer.WriteAttributeString("Namespace", SolutionBuilder.TargetName);
        writer.WriteAttributeString("TypeName", "*");
        writer.WriteAttributeString("Safe", "True");
        writer.WriteEndElement();
        writer.WriteEndElement();
        writer.WriteEndElement();
        writer.WriteEndElement();
      }

      if (CasPermissions != null) {
        writer.WriteStartElement("CodeAccessSecurity");
        writer.WriteStartElement("PolicyItem");
        writer.WriteStartElement("PermissionSet");
        writer.WriteAttributeString("class", "NamedPermissionSet");
        writer.WriteAttributeString("version", "1");
        writer.WriteAttributeString("Name", SolutionBuilder.TargetName);
        // write out each CAS permission as an IPermission element
        foreach (SecurityElement se in CasPermissions.ToXml().Children) {
          writer.WriteStartElement("IPermission");
          foreach (DictionaryEntry de in se.Attributes) {
            writer.WriteAttributeString(de.Key.ToString(), de.Value.ToString());
          }
          writer.WriteEndElement(); // </IPermission>
        }
        writer.WriteEndElement(); // </PermissionSet>
        writer.WriteStartElement("Assemblies");
        writer.WriteStartElement("Assembly");
        writer.WriteAttributeString("Name", SolutionBuilder.TargetName + ".dll");
        writer.WriteEndElement(); // </Assembly>
        writer.WriteEndElement(); // </Assemblies>
        writer.WriteEndElement(); // </PolicyItem>
        writer.WriteEndElement(); // </CodeAccessSecurity>  
      }

      writer.WriteEndElement(); // </Solution>
      writer.WriteEndDocument();
      writer.Close();
      manifestStream.Close();
    }
  }
}
